home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-08-10 | 35.4 KB | 1,091 lines | [TEXT/CWIE] |
- /*************************************************************************************
- TTileCollection.cp
-
- A TileCollection is a set of tiles that can be used to draw a grid. Essentially,
- this class performs the same function that the TGraphicCollection class does, but
- it is designed just to draw 32x32x8 tiles. By making this code as specific as
- possible, this code is more than twice as fast as using TGraphics to draw the tiles.
-
- Author: Timothy Carroll
- Apple Developer Technical Support
- timc@apple.com
-
- Modification History:
-
- 1/23/97 TMC Added include for Moofwars.h so that MrC will compile
- 8/15/96 TMC Initial Release
-
- Copyright © 1996, 1997 Apple Computer, Inc., All Rights Reserved
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- *************************************************************************************/
-
- #include <Memory.h>
- #include <Resources.h>
-
-
- #include "Moofwars.h"
- #include "TTileCollection.h"
- #include "Scaling.h"
-
- #include "GridTilesFormat.h"
-
-
- const int kTileSize = 1024;
- const int kTileGroupSize = (kTileSize+1)*8;
-
- /*************************************************************************************
-
- Internal Declarations
-
- We will hold the list of created TTileCollection objects in a handle. This handle is
- automatically created the first time we load a TTileCollection and is deallocated when
- the list is empty.
-
- All of the allocation and deallocation is handled by the static NewCollection call.
-
- NewCollection has a few utility routines it calls on to manage the handle. Mainly they do
- the searching, insertion and deletion from the list.
- *************************************************************************************/
-
- static Handle gTileCollectionList = NULL;
- static unsigned long gNumberItemsInList = 0;
-
-
-
- static OSErr InsertCollectionIntoList (TTileCollection *theCollection, UInt32 index);
- static OSErr DeleteCollectionFromList (UInt32 index);
- static OSErr SearchCollectionList (SInt16 resID, Boolean *found, UInt32 *index);
-
- /*************************************************************************************
- InsertCollectionIntoList
-
- This routine creates the handle if necessary, and otherwise inserts the TTileCollection
- into the list at the index location given.
-
- Assumptions:
- theCollection must be a legitimate TTileCollection -- no NULL parameters.
- index must be no more than 1 larger than gNumberItemsInList. ?????
- *************************************************************************************/
-
- OSErr InsertCollectionIntoList (TTileCollection *theCollection, UInt32 index)
- {
- OSErr theErr = noErr;
-
- #if qDebugging
- if (index > gNumberItemsInList)
- SIGNAL_ERROR ("\pAttempting to insert collection at invalid index")
- if (theCollection == NULL)
- SIGNAL_ERROR ("\pAttempting to insert a null collection into the list")
-
- #endif
-
- if (gTileCollectionList == NULL)
- {
- gNumberItemsInList = 1;
-
- gTileCollectionList = NewHandleClear (sizeof (TTileCollection *));
- theErr = MemError();
-
- FAIL_OSERR (theErr, "\pCouldn't allocate a new handle of information")
- FAIL_NIL (gTileCollectionList, "\pCouldn't allocate a new handle of information")
-
- }
- else
- {
- gNumberItemsInList++;
- SetHandleSize(gTileCollectionList,gNumberItemsInList*sizeof(TTileCollection *));
-
- theErr = MemError();
- FAIL_OSERR (theErr, "\pCouldn't resize the list handle")
- FAIL_NIL (gTileCollectionList, "\pCouldn't resize the list handle")
-
- // Shift the data to make room
- BlockMoveData( (*(TTileCollection ***)gTileCollectionList)+index,
- (*(TTileCollection ***)gTileCollectionList)+index+1,
- (gNumberItemsInList - index-1) * sizeof(TTileCollection *));
- }
-
- // finally, set the new object in place
- *((*(TTileCollection ***) gTileCollectionList)+index) = theCollection;
-
- return noErr;
-
- error:
-
-
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
-
-
- /*************************************************************************************
- DeleteCollectionFromList
-
- This routine removes the collection from the list and destroys it. If there are no more items
- in the list then we dispose of the handle.
-
- Assumptions:
- index must be within the list.
- *************************************************************************************/
- OSErr DeleteCollectionFromList (UInt32 index)
- {
- OSErr theErr;
-
- gNumberItemsInList--;
-
- // slide remaining elements up
-
- BlockMoveData( (*(TTileCollection ***)gTileCollectionList)+index+1,
- (*(TTileCollection ***)gTileCollectionList)+index,
- (gNumberItemsInList - index) * sizeof(TTileCollection *));
-
- // cut back the storage and dispose of the handle if we have no items left
-
-
- if (gNumberItemsInList> 0)
- {
- SetHandleSize((Handle) gTileCollectionList,gNumberItemsInList*sizeof(TTileCollection *));
- theErr = MemError();
- FAIL_OSERR (theErr, "\pCouldn't resize the list handle")
- FAIL_NIL (gTileCollectionList, "\pCouldn't resize the list handle")
- }
-
- else
- {
- DisposeHandle (gTileCollectionList);
- gTileCollectionList = NULL;
- }
-
-
- return noErr;
- error:
-
-
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
-
-
- /*************************************************************************************
- SearchCollectionList
-
- This routine searches through the list and attempts to find an existing TTileCollection with
- that resID. If it finds one with that resID, then it returns the index to that collection and
- sets found to true. If it doesn't find that resource, then it sets found to false AND sets the
- index to where it should be inserted into the list.
- *************************************************************************************/
- OSErr SearchCollectionList (SInt16 resID, Boolean *found, UInt32 *index)
- {
- UInt32 low = 0;
- UInt32 high = gNumberItemsInList;
- UInt32 tempIndex;
- TTileCollection *theItem;
-
- OSErr theErr = noErr;
-
- *found = false;
-
- while (low < high)
- {
- tempIndex = (low+high) >> 1;
-
- theItem = (*(TTileCollection ***)gTileCollectionList)[tempIndex];
-
- FAIL_NIL (theItem, "\pBad TTile object")
-
- if (resID < theItem->GetResID())
- high = tempIndex; // element is below "high"
- else if (resID == theItem->GetResID())
- {
- *found = true;
- *index = tempIndex;
- return noErr;
- }
- else
- low = tempIndex+1; // element is above "low"
- }
-
- // use final calculations to put insert in the right place in the list
- *index = (low+high) >> 1;
- return noErr;
-
- error:
-
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
-
-
- }
- /*************************************************************************************
- TTileCollection::NewCollection
-
- This routine merely uses the routines we created above to properly create and load
- the TTileCollections.
- *************************************************************************************/
- TTileCollection
- *TTileCollection::NewCollection (SInt16 resID)
- {
- unsigned long listIndex;
- Boolean tableAlreadyExists;
- TTileCollection *newCollection = NULL;
- OSErr theErr;
-
- theErr = SearchCollectionList (resID, &tableAlreadyExists, &listIndex);
- FAIL_OSERR(theErr,"\pCouldn't search the collection list in TTileCollection::NewCollection")
-
- if (tableAlreadyExists)
- {
- // find the existing collection and add 1 to the ref count.
- newCollection = (*(TTileCollection ***)gTileCollectionList)[listIndex];
- newCollection->AddReference();
- }
- else
- {
- // create a new collection
- newCollection = new TTileCollection(resID);
- theErr = newCollection->CreateCollection ();
- FAIL_OSERR(theErr,"\pCouldn't create new TTileCollection")
- theErr = InsertCollectionIntoList(newCollection, listIndex);
- FAIL_OSERR(theErr, "\pCouldn't add new TTileCollection to list")
- newCollection->AddReference();
- }
-
- return newCollection;
- error:
- if (newCollection != NULL)
- delete newCollection;
- return NULL;
- }
-
-
- /*************************************************************************************
- TTileCollection::AddReference
- *************************************************************************************/
-
- void
- TTileCollection::AddReference (void)
- {
- fReferenceCount++;
- }
-
-
- /*************************************************************************************
- TTileCollection::DisposeReference
- *************************************************************************************/
-
- void
- TTileCollection::DisposeReference (void)
- {
- fReferenceCount--;
- if (fReferenceCount == 0)
- {
- UInt32 listIndex;
- Boolean tableEntry;
- OSErr theErr;
-
- theErr = SearchCollectionList (fResID, &tableEntry, &listIndex);
-
- FAIL_OSERR (theErr, "\pFailed to search the CollectionList")
- FAIL_FALSE (tableEntry, "\pFailed to find an existing TTileCollection in list")
-
- theErr = DeleteCollectionFromList(listIndex);
- FAIL_OSERR (theErr, "\pFailed to delete Collection from the list")
-
- delete this;
- }
-
- error:
- return;
- }
-
-
- /*************************************************************************************
- TTileCollection::TTileCollection
-
- All of the actual work is done in CreateCollection
- *************************************************************************************/
-
- TTileCollection::TTileCollection (SInt16 resID)
- {
- fResID = resID;
- fReferenceCount = 0;
- fNumberOfTiles = 0;
- fTiles = NULL;
- }
-
-
- /*************************************************************************************
- TTileCollection::~TTileCollection
-
- All of the actual work is done in DeleteCollection
- *************************************************************************************/
-
- TTileCollection::~TTileCollection (void)
- {
- if (fTiles != NULL)
- {
- OSErr theErr = DestroyCollection();
- FAIL_OSERR (theErr, "\pFailed to destroy the TTileCollection data")
- }
-
- error:
- return;
- }
-
-
- /*************************************************************************************
- TTileCollection::CreateCollection
-
- This routine uses the resource number we passed into the contructor to load the TTileCollection
- from the 'SptA' resource we created for it. Note that we don't make any assumptions about
- the resource file being used, so the correct resource file already needs to be opened for this
- call to work.
- *************************************************************************************/
-
- OSErr TTileCollection::CreateCollection(void)
- {
- OSErr theErr = noErr;
- TileCollectionResHeader **tiles;
- int loop;
- Ptr srcPtr, destPtr;
-
- // Load the 'TILE' resource and check to make sure we can read the header information.
-
- tiles = (TileCollectionResHeader **) Get1Resource (TileCollectionResType, fResID);
- theErr = ResError();
-
- FAIL_OSERR (theErr, "\pFailed to load the TILE resource.")
- FAIL_NIL (tiles, "\pFailed to load the TILE resource.")
-
- if ( (**tiles).version != 0) SIGNAL_ERROR ("\pInvalid version number in TILE resource")
- if ( (**tiles).depth != 8) SIGNAL_ERROR ("\pInvalid Pixel Depth in TILE resource")
- fNumberOfTiles = (**tiles).numTiles;
-
- fTiles = NewHandle (fNumberOfTiles * kTileGroupSize);
- theErr = MemError();
-
- FAIL_OSERR (theErr, "\pFailed to allocate memory for the tiles")
- FAIL_NIL (fTiles, "\pFailed to allocate memory for the tiles")
-
- srcPtr = (Ptr)(*tiles) + sizeof (TileCollectionResHeader);
- destPtr = (*fTiles);
-
- fTileOffset = (fNumberOfTiles * kTileSize) +1;
- for (loop = 0; loop < 8; loop++)
- {
- BlockMoveData (srcPtr, destPtr, kTileSize*fNumberOfTiles);
- destPtr += fTileOffset;
- }
-
- // Completed successfully, cleanup and exit with no error;
- goto cleanup;
-
- error:
- if (theErr == noErr)
- theErr = paramErr;
-
- if (fTiles != NULL)
- DisposeHandle (fTiles);
- fTiles = NULL;
-
- cleanup:
-
- if (tiles != NULL)
- ReleaseResource ((Handle) tiles);
-
- return theErr;
- }
-
-
- /*************************************************************************************
- TTileCollection::DestroyCollection
-
- Throw away all of the objects that we're created. We do check for null TTile objects here,
- and properly skip null objects that might not have been finished from the create calls.
- *************************************************************************************/
-
- OSErr
- TTileCollection::DestroyCollection (void)
- {
- if (fTiles != NULL)
- DisposeHandle (fTiles);
- fTiles = NULL;
-
- return noErr;
- }
-
-
-
- /*************************************************************************************
- TTileCollection::LockCollection
-
- *************************************************************************************/
-
- OSErr
- TTileCollection::LockCollection (void)
- {
- OSErr theErr = noErr;
-
- MoveHHi (fTiles);
- theErr = MemError();
- FAIL_OSERR (theErr, "\pCouldn't move fTiles handle high")
- HLock (fTiles);
- theErr = MemError();
- FAIL_OSERR (theErr, "\pCouldn't lock fTiles handle")
-
- error:
- return theErr;
- }
-
-
- /*************************************************************************************
- TTileCollection::UnlockCollection
-
- *************************************************************************************/
-
- OSErr
- TTileCollection::UnlockCollection (void)
- {
- OSErr theErr = noErr;
-
- HUnlock (fTiles);
- theErr = MemError();
- FAIL_OSERR (theErr, "\pCouldn't unlock fTiles handle")
-
- error:
- return theErr;
- }
-
-
- /*************************************************************************************
- TTileCollection::CopyImageUnclipped
-
- This is a set of optimized image copying routines that take advantage of alignment for some serious
- speed improvements. These routines take the destination pointer and assume that the image being
- copied is completely on the screen. If your routine can't determine which of these routines to
- call, call CopyImageClip instead.
-
- Now for a more detailed discussion of these routines and why we actually go about this. The main
- advantage to these routines is that their specialization allows them to be much faster than the
- generic copying loop in the TGraphic class.
-
- The fastest way to move memory on PPC is usually to load and store float doubles, which are 64 bits
- wide. The problem is that if you decide to move doubles, you need to guarantee alignment to an
- 8 byte boundary, or your code will run slow on a 603 and 604 processor. For the generic sprite
- blitter, it was faster to just move longs and let the hardware deal with address misalignment. But
- for tiles, we can make copies of the same data at different alignments and use the correct data
- when drawing to the screen. In fact, we could do this for sprites too. The main advantage is that
- because we know the width of the tile, we can write a blitter loop that has no logic in it other
- than loads and stores. At one point, I did attempt to write a variable length blitter that did the
- same thing, but for small sprites, the overhead of checking for the correct sprite was always more
- than just drawing with longs.
-
- In any case, each of these blitters performs every load and every store on an exact boundary, with
- no misalignments. This results in much faster code in general, and also lets us load data into
- the floats and stores.
-
- Future possibilities:
-
- * The cache touch instructions might be useful to make sure that the source data is loaded well ahead
- of each time through the loop. This can help performance, and is also possible to do for the
- destination if the destination is cacheable. I haven't experimented with this yet, but probably
- will in the future.
-
- * Currently the largest number of loads for a single line is 7 (CopyImageUnclipped1). Because the
- next line starts immediately after the previous line in memory, we can probably replace 3 of the
- loads (load char, load char, load short) with a single load long, and use shifts to get the correct
- data. This won't do much to reduce the number of stores, but might improve performance slightly.
-
- *************************************************************************************/
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped0
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped0 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3, double4;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
- // load all the data into the registers
-
- double1 = *((double *) srcPtr);
- double2 = *((double *) srcPtr+1);
- double3 = *((double *) srcPtr+2);
- double4 = *((double *) srcPtr+3);
-
- // dump all the data out to the destination.
-
- *((double *) destPtr) = double1;
- *((double *) destPtr+1) = double2;
- *((double *) destPtr+2) = double3;
- *((double *) destPtr+3) = double4;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped1
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped1 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned char char1,char2;
- register unsigned short short1;
- register unsigned long long1;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
-
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index + fTileOffset);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
- // load all the data into the registers. We're one byte misaligned, so we need to load 7 bytes before
- // we hit the next 8-byte boundary.
-
- char1 = *((unsigned char *) srcPtr);
- short1 = *((unsigned short *) ((unsigned char *) srcPtr+1));
- long1 = *((unsigned long *) ((unsigned char *) srcPtr+3));
- double1 = *((double *) ((unsigned char *) srcPtr+7));
- double2 = *((double *) ((unsigned char *) srcPtr+15));
- double3 = *((double *) ((unsigned char *) srcPtr+23));
- char2 = *((unsigned char *) ((unsigned char *) srcPtr+31));
-
- srcPtr += 32;
-
- // dump all the data out to the destination.
-
- *((unsigned char *) ((unsigned char *) destPtr)) = char1;
- *((unsigned short *) ((unsigned char *) destPtr+1)) = short1;
- *((unsigned long *) ((unsigned char *) destPtr+3)) = long1;
- *((double *) ((unsigned char *) destPtr+7)) = double1;
- *((double *) ((unsigned char *) destPtr+15)) = double2;
- *((double *) ((unsigned char *) destPtr+23)) = double3;
- *((unsigned char *) ((unsigned char *) destPtr+31)) = char2;
-
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped2
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped2 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned short short1, short2;
- register unsigned long long1;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
-
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index + fTileOffset*2);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
-
- // load all the data into the registers
-
- short1 = *((unsigned short *) srcPtr);
- long1 = *((unsigned long *) ((unsigned char *) srcPtr+2));
- double1 = *((double *) ((unsigned char *) srcPtr+6));
- double2 = *((double *) ((unsigned char *) srcPtr+14));
- double3 = *((double *) ((unsigned char *) srcPtr+22));
- short2 = *((unsigned short *) ((unsigned char *) srcPtr+30));
-
- // dump all the data out to the destination.
- *((unsigned short *) ((unsigned char *) destPtr)) = short1;
- *((unsigned long *) ((unsigned char *) destPtr+2)) = long1;
- *((double *) ((unsigned char *) destPtr+6)) = double1;
- *((double *) ((unsigned char *) destPtr+14)) = double2;
- *((double *) ((unsigned char *) destPtr+22)) = double3;
- *((unsigned short *) ((unsigned char *) destPtr+30)) = short2;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped3
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped3 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned char char1,char2;
- register unsigned short short1;
- register unsigned long long1;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index + fTileOffset*3);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
-
- // load all the data into the registers
-
- char1 = *((unsigned char *) srcPtr);
- long1 = *((unsigned long *) ((unsigned char *)srcPtr+1));
- double1 = *((double *) ((unsigned char *)srcPtr+5));
- double2 = *((double *) ((unsigned char *)srcPtr+13));
- double3 = *((double *) ((unsigned char *)srcPtr+21));
- char2 = *((unsigned char *) ((unsigned char *)srcPtr+29));
- short1 = *((unsigned short *) ((unsigned char *)srcPtr+30));
-
- // dump all the data out to the destination.
- *((unsigned char *) ((unsigned char *) destPtr)) = char1;
- *((unsigned long *) ((unsigned char *) destPtr+1)) = long1;
- *((double *) ((unsigned char *) destPtr+5)) = double1;
- *((double *) ((unsigned char *) destPtr+13)) = double2;
- *((double *) ((unsigned char *) destPtr+21)) = double3;
- *((unsigned char *) ((unsigned char *) destPtr+29)) = char2;
- *((unsigned short *)((unsigned char *) destPtr+30)) = short1;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped4
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped4 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned long long1, long2;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
- //srcPtr = (unsigned char *) ((*fTiles) + alignment * fTileOffset + kTileSize*index);
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index + 4*fTileOffset);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
- long1 = *((unsigned long *) ((unsigned char *)srcPtr));
- double1 = *((double *) ((unsigned char *)srcPtr+4));
- double2 = *((double *) ((unsigned char *)srcPtr+12));
- double3 = *((double *) ((unsigned char *)srcPtr+20));
- long2 = *((unsigned long *) ((unsigned char *)srcPtr+28));
-
- // dump all the data out to the destination.
- *((unsigned long *) ((unsigned char *) destPtr)) = long1;
- *((double *) ((unsigned char *) destPtr+4)) = double1;
- *((double *) ((unsigned char *) destPtr+12)) = double2;
- *((double *) ((unsigned char *) destPtr+20)) = double3;
- *((unsigned long *) ((unsigned char *) destPtr+28)) = long2;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
-
- error:
- return;
- }
-
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped5
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped5 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned char char1,char2;
- register unsigned short short1;
- register unsigned long long1;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index + 5*fTileOffset);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
-
- // load all the data into the registers
- char1 = *((unsigned char *) ((unsigned char *) srcPtr+0));
- short1 = *((unsigned short *) ((unsigned char *) srcPtr+1));
- double1 = *((double *) ((unsigned char *) srcPtr+3));
- double2 = *((double *) ((unsigned char *) srcPtr+11));
- double3 = *((double *) ((unsigned char *) srcPtr+19));
- long1 = *((unsigned long *) ((unsigned char *) srcPtr+27));
- char2 = *((unsigned char *) ((unsigned char *) srcPtr+31));
-
- *((unsigned char *) ((unsigned char *) destPtr+0)) = char1;
- *((unsigned short *)((unsigned char *) destPtr+1)) = short1;
- *((double *) ((unsigned char *) destPtr+3)) = double1;
- *((double *) ((unsigned char *) destPtr+11)) = double2;
- *((double *) ((unsigned char *) destPtr+19)) = double3;
- *((unsigned long *) ((unsigned char *) destPtr+27)) = long1;
- *((unsigned char *) ((unsigned char *) destPtr+31)) = char2;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
- /***************************************
- TTileCollection::CopyImageUnclipped6
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped6 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned short short1, short2;
- register unsigned long long1;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
- //srcPtr = (unsigned char *) ((*fTiles) + alignment * fTileOffset + kTileSize*index);
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index + 6*fTileOffset);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
-
- short1 = *((unsigned short *) ((unsigned char *) srcPtr+0));
- double1 = *((double *) ((unsigned char *) srcPtr+2));
- double2 = *((double *) ((unsigned char *) srcPtr+10));
- double3 = *((double *) ((unsigned char *) srcPtr+18));
- long1 = *((unsigned long *) ((unsigned char *) srcPtr+26));
- short2 = *((unsigned short *) ((unsigned char *) srcPtr+30));
-
- *((unsigned short *)((unsigned char *) destPtr+0)) = short1;
- *((double *) ((unsigned char *) destPtr+2)) = double1;
- *((double *) ((unsigned char *) destPtr+10)) = double2;
- *((double *) ((unsigned char *) destPtr+18)) = double3;
- *((unsigned long *) ((unsigned char *) destPtr+26)) = long1;
- *((unsigned short *)((unsigned char *) destPtr+30)) = short2;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
-
- /***************************************
- TTileCollection::CopyImageUnclipped7
- ****************************************/
- void
- TTileCollection::CopyImageUnclipped7 (UInt32 index, unsigned char *destPtr)
- {
- register double double1, double2, double3;
- register unsigned char char1,char2;
- register unsigned short short1;
- register unsigned long long1;
-
- unsigned char *srcPtr; // the current position in the sprite data
- int loop;
- int rowBytesLocal; // used to hold the rowbytes value to eliminate a load.
-
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
- //srcPtr = (unsigned char *) ((*fTiles) + alignment * fTileOffset + kTileSize*index);
- srcPtr = (unsigned char *) ((*fTiles) + kTileSize*index+ 7*fTileOffset);
- rowBytesLocal = gRowBytes;
-
- for (loop = 0; loop < 32; loop++)
- {
-
- char1 = *((unsigned char *) ((unsigned char *) srcPtr+0));
- double1 = *((double *) ((unsigned char *) srcPtr+1));
- double2 = *((double *) ((unsigned char *) srcPtr+9));
- double3 = *((double *) ((unsigned char *) srcPtr+17));
- long1 = *((unsigned long *) ((unsigned char *) srcPtr+25));
- short1 = *((unsigned short *) ((unsigned char *) srcPtr+29));
- char2 = *((unsigned char *) ((unsigned char *) srcPtr+31));
-
- *((unsigned char *) ((unsigned char *) destPtr+0)) = char1;
- *((double *) ((unsigned char *) destPtr+1)) = double1;
- *((double *) ((unsigned char *) destPtr+9)) = double2;
- *((double *) ((unsigned char *) destPtr+17)) = double3;
- *((unsigned long *) ((unsigned char *) destPtr+25)) = long1;
- *((unsigned short *)((unsigned char *) destPtr+29)) = short1;
- *((unsigned char *) ((unsigned char *) destPtr+31)) = char2;
-
- srcPtr += 32;
- destPtr += rowBytesLocal;
- }
-
- error:
- return;
- }
-
-
- /*************************************************************************************
- TTileCollection::CopyImageClipped
-
- CopyImageClipped also draws the image, but always checks to make sure that it is inside the
- designated drawing area set in the clipping rectangle for our drawing code. For the moment, this
- version of the code always does the drawing using simple long moves without regard to alignment.
-
- *************************************************************************************/
-
- void
- TTileCollection::CopyImageClipped (UInt32 index, SInt32 top, SInt32 left)
- {
- #if qDebugging
- if (gDestPixMap == NULL)
- SIGNAL_ERROR ("\pAttempting to draw to a NULL destination pixmap")
-
- if (EmptyRect (&gClipRect))
- SIGNAL_ERROR ("\pEmpty Clipping Region")
-
- if (index >= fNumberOfTiles)
- // We're outside of the bounds of the Tiles table here. Debugger time! :-)
- SIGNAL_ERROR("\ptried to index a TTile that was out of bounds");
- #endif
-
- // We'll do all our calculations in variables rather than use a structure.
- // hopefully this should speed things up
- SInt32 destTop, destBottom, destLeft, destRight;
-
- destTop = top;
- destBottom = top+32;
- destLeft = left;
- destRight = left+32;
-
- // determine if the spite needs to be drawn at all
- if (destTop >= gClipRect.bottom || destBottom <= gClipRect.top ||
- destLeft >= gClipRect.right || destRight <= gClipRect.left )
- // no need to draw, goodbye
- return;
-
- // determine if the sprite will be clipped
- if (destTop < gClipRect.top || destBottom > gClipRect.bottom ||
- destLeft < gClipRect.left || destRight > gClipRect.right)
- {
- UInt32 clipTop, clipBottom, clipLeft, clipRight;
- unsigned char *srcPtr; // the current position in the tile data
- unsigned char *destPtr; // the current position in the destination pixmap
- unsigned long blitwidth, blitheight;
- unsigned long yLoop;
- unsigned long sourceOffset, destOffset;
-
- // Calculate clipping rectangle.
- clipTop = destTop < gClipRect.top ? gClipRect.top - destTop : 0;
- clipBottom = destBottom > gClipRect.bottom ? gClipRect.bottom-destTop : destBottom-destTop;
- clipLeft = destLeft < gClipRect.left ? gClipRect.left-destLeft : 0;
- clipRight = destRight > gClipRect.right ? gClipRect.right-destLeft : destRight-destLeft;
-
- // calculate source and destination pointers
- srcPtr = ( unsigned char * )( *fTiles ) + kTileSize*index;
- srcPtr += 32*clipTop+clipLeft;
-
- destPtr = gDestBaseAddr + (top + clipTop) * gRowBytes + left + clipLeft;
-
- // how much do we actually need to draw?
- blitwidth = clipRight - clipLeft;
- blitheight = clipBottom - clipTop;
- sourceOffset = 32-blitwidth;
- destOffset = gRowBytes-blitwidth;
-
- for (yLoop = 0; yLoop < blitheight; yLoop++)
- {
- register unsigned long sixteenblits, blitloop;
- sixteenblits = blitwidth >> 4;
- for ( blitloop = 0; blitloop < sixteenblits; blitloop++)
- {
- register unsigned long temp1, temp2, temp3, temp4;
- temp1 = ((unsigned long *) srcPtr)[0];
- temp2 = ((unsigned long *) srcPtr)[1];
- temp3 = ((unsigned long *) srcPtr)[2];
- temp4 = ((unsigned long *) srcPtr)[3];
- ((unsigned long *) destPtr)[0] = temp1;
- ((unsigned long *) destPtr)[1] = temp2;
- ((unsigned long *) destPtr)[2] = temp3;
- ((unsigned long *) destPtr)[3] = temp4;
- srcPtr += 16;
- destPtr += 16;
- }
- // move any remaining data, up to 15 bytes total
- if (blitwidth & 0x8)
- {
- register unsigned long temp1, temp2;
- temp1 = ((unsigned long *) srcPtr)[0];
- temp2 = ((unsigned long *) srcPtr)[1];
- ((unsigned long *) destPtr)[0] = temp1;
- ((unsigned long *) destPtr)[1] = temp2;
- srcPtr += 8;
- destPtr += 8;
- }
- if (blitwidth & 0x4)
- {
- register unsigned long temp1;
- temp1 = *((unsigned long *) srcPtr);
- srcPtr +=4;
- *((unsigned long *) destPtr) = temp1;
- destPtr +=4;
- }
- if (blitwidth & 0x2)
- {
- register unsigned short temp1;
- temp1 = *((unsigned short *) srcPtr);
- srcPtr +=2;
- *((unsigned short *) destPtr) = temp1;
- destPtr +=2;
- }
- if (blitwidth & 0x1)
- *destPtr++ = *srcPtr++;
- srcPtr += sourceOffset;
- destPtr += destOffset;
- }
-
- }
- else
- {
- // Unclipped, so calculate the destination pointer and alignment and call the appropriate unclipped case.
- unsigned char *destPtr; // the current position in the destination pixmap
- long alignment;
-
-
- destPtr = gDestBaseAddr + top * gRowBytes + left;
- alignment = ((long) destPtr) & 0x07;
- switch (alignment)
- {
- case 0: CopyImageUnclipped0 (index, destPtr); break;
- case 1: CopyImageUnclipped1 (index, destPtr); break;
- case 2: CopyImageUnclipped2 (index, destPtr); break;
- case 3: CopyImageUnclipped3 (index, destPtr); break;
- case 4: CopyImageUnclipped4 (index, destPtr); break;
- case 5: CopyImageUnclipped5 (index, destPtr); break;
- case 6: CopyImageUnclipped6 (index, destPtr); break;
- case 7: CopyImageUnclipped7 (index, destPtr); break;
- }
- }
-
- error:
- return;
- }